import sys
import threading
import time
import unittest
from .utils import getLogger
from .keaUtils import KeaPropRunner, KeaRPCRunner, Options, RESFILE, KeaTestProgram, KeaPropLoader
from .sync import PropSemaphore, PropertyExecManager, PropExecutionInfo
from .hypiumDriver import HDriver
import os


from pathlib import Path
DEFAULT_ROOT = str(Path(__file__).parent.parent / "hypiumtests")

logger = getLogger(__name__)
    
    
class Kea2:

    def __init__(self, device_sn=None, driverName="d", root_dir:str = None):
        """
        init the Kea2 PBT framework

        :param device_sn: the device serial of device_sn
        :param driverName: the name of driver written in script.
        :param root_dir: the root dir for finding the PBT TestCases. (explore all *.py in its decedents)
        """
        self.start_time = time.perf_counter()
        HDriver.initializer(
            device_sn=device_sn
        )

        self.root_dir = (
            root_dir if root_dir is not None
            else DEFAULT_ROOT
        )

        output_dir = os.path.join(self.root_dir, "output")

        KeaPropRunner.setOptions(
            Options(
                driverName=driverName,
                Driver=HDriver,
                packageNames=["com.hmosworld.wayne"],
                output_dir=output_dir
            )
        )

        self.start_time = time.perf_counter()

        self.runner = KeaPropRunner
        self.output_dir = self.runner.options.output_dir if hasattr(self.runner, 'options') else None
        self.result_file = RESFILE

    def _run_unittest(self):
        # sys.argv = ["python3", "-m", "unittest", "discover", "-s", TEST_ROOT, "-p", "*.py"]
        argv = ["unittest", "discover", "-s", self.root_dir, "-p", "*.py"]

        # unittest.main(module=None, testRunner=self.runner, argv=argv, testLoader=PropLoader())
        KeaTestProgram(module=None, testRunner=self.runner, argv=argv, testLoader=KeaPropLoader())

    def start(self) -> None:
        """
        start the kea2 PBT framework
        """
        self._thread = threading.Thread(target=self._run_unittest, daemon=True)
        self.semaphore = PropSemaphore()
        self._thread.start()
        self.output_dir = self.runner.options.output_dir if hasattr(self.runner, 'options') else None
        self.result_file = RESFILE

    def get_test_time(self) -> float:
        """
        Get the total test time in seconds.
        """
        return time.perf_counter() - self.start_time

    def get_test_app(self) -> str:
        """
        Get the test application package name.
        """
        if hasattr(self.runner, 'options') and self.runner.options and self.runner.options.packageNames:
            return ', '.join(self.runner.options.packageNames)
        return "com.hmosworld.wayne"  # 默认应用包名

    def exec_prop(self):
        """
        Call kea2 to check properties.
        """
        self.semaphore.execProp.release()
        self.semaphore.finishProp.acquire()

        self.update_bug_report()

    def exec_before_monkey(self):
        self.semaphore.before_monkey.release()
        self.semaphore.before_monkey_done.acquire()

    def exec_after_monkey(self):
        self.semaphore.after_monkey.release()
        self.semaphore.after_monkey_done.acquire()

    def update_bug_report(self):
        try:
            self.output_dir = self.runner.options.output_dir if hasattr(self.runner, 'options') else None

            if self.output_dir and os.path.exists(self.output_dir):
                if not os.path.isabs(self.result_file):
                    result_file_path = os.path.join(self.output_dir, os.path.basename(self.result_file))
                else:
                    result_file_path = self.result_file

                # 计算测试时长并获取测试应用信息
                test_duration = self.get_test_time()
                test_app = self.get_test_app()
                report_path = generate_html_report(self.output_dir, result_file_path, test_duration, test_app)
                logger.info(f"[INFO] Test report generated: {report_path}")
        except Exception as e:
            logger.error(f"[ERROR] Failed to generate final report: {str(e)}")
            import traceback
            traceback.print_exc()
    
        
    def get_test_time(self) -> float:
        """
        get the test time in seconds
        """
        return time.perf_counter() - self.start_time

    def tearDown(self):
        """
        teardown the kea2 PBT framework
        """
        self.semaphore.exit.set()
        self._thread.join()
        
        try:
            self.output_dir = self.runner.options.output_dir if hasattr(self.runner, 'options') else None
            
            if self.output_dir and os.path.exists(self.output_dir):
                if not os.path.isabs(self.result_file):
                    result_file_path = os.path.join(self.output_dir, os.path.basename(self.result_file))
                else:
                    result_file_path = self.result_file
                    
        #         # 计算测试时长并获取测试应用信息
        #         test_duration = self.get_test_time()
        #         test_app = self.get_test_app()
        #         report_path = generate_html_report(self.output_dir, result_file_path, test_duration, test_app)
        #         logger.info(f"[INFO] Test report generated: {report_path}")
        # except Exception as e:
        #     logger.error(f"[ERROR] Failed to generate final report: {str(e)}")
        #     import traceback
        #     traceback.print_exc()


class Kea2_RPC:

    def __init__(self, device_sn=None, driverName="d", root_dir: str = None):
        """
        init the Kea2 PBT framework

        :param device_sn: the device serial of device_sn
        :param driverName: the name of driver written in script.
        :param root_dir: the root dir for finding the PBT TestCases. (explore all *.py in its decedents)
        """
        HDriver.initializer(
            device_sn=device_sn
        )

        self.root_dir = (
            root_dir if root_dir is not None
            else DEFAULT_ROOT
        )

        output_dir = os.path.join(self.root_dir, "output")

        KeaRPCRunner.setOptions(
            Options(
                driverName=driverName,
                Driver=HDriver,
                packageNames=["com.hmosworld.wayne"],
                output_dir=output_dir
            )
        )

        self.runner = KeaRPCRunner
        self.output_dir = self.runner.options.output_dir if hasattr(self.runner, 'options') else None
        self.result_file = RESFILE

    def _run_unittest(self):
        # sys.argv = ["python3", "-m", "unittest", "discover", "-s", TEST_ROOT, "-p", "*.py"]
        argv = ["unittest", "discover", "-s", self.root_dir, "-p", "*.py"]

        # unittest.main(module=None, testRunner=self.runner, argv=argv, testLoader=PropLoader())
        KeaTestProgram(module=None, testRunner=self.runner, argv=argv, testLoader=KeaPropLoader())

    def start(self) -> None:
        """
        start the kea2 PBT framework
        """
        self._thread = threading.Thread(target=self._run_unittest, daemon=True)
        self.propExecManager = PropertyExecManager()
        self._thread.start()

    def exec_prop(self) -> PropExecutionInfo:
        """
        Call kea2 to check properties.
        """
        self.propExecManager.switch_controller("kea2")
        while not self.propExecManager.monkey_runing.wait(timeout=0.05):
            pass
        return self.propExecManager.propExecInfo

    def clearPropExecInfo(self):
        self.propExecManager.propExecInfo.clear()

    def tearDown(self):
        """
        teardown the kea2 PBT framework
        """
        self.propExecManager.exit()
        self._thread.join()
